﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using HtmlAgilityPack;


namespace Nasa8x.Core
{
    public static class Utils
    {
//        private static readonly Regex _tags = new Regex("<[^>]*(>|$)",
//   RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled);
//        private static readonly Regex _whitelist = new Regex(@"
//    ^</?(b(lockquote)?|code|d(d|t|l|el)|em|h(1|2|3)|i|kbd|li|ol|p(re)?|s(ub|up|trong|trike)?|ul)>$|
//    ^<(b|h)r\s?/?>$",
//            RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);
//        private static readonly Regex _whitelist_a = new Regex(@"
//    ^<a\s
//    href=""(\#\d+|(https?|ftp)://[-a-z0-9+&@#/%?=~_|!:,.;\(\)]+)""
//    (\stitle=""[^""<>]+"")?\s?>$|
//    ^</a>$",
//            RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);
//        private static readonly Regex _whitelist_img = new Regex(@"
//    ^<img\s
//    src=""https?://[-a-z0-9+&@#/%?=~_|!:,.;\(\)]+""
//    (\swidth=""\d{1,3}"")?
//    (\sheight=""\d{1,3}"")?
//    (\salt=""[^""<>]*"")?
//    (\stitle=""[^""<>]*"")?
//    \s?/?>$",
//            RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);


        #region private method
        private static string RemoveExtraHyphen(string text)
        {
            const string replace = "--";
            if (text.Contains(replace))
            {
                text = text.Replace(replace, "-");
                return RemoveExtraHyphen(text);
            }

            return text;
        }
        #endregion


        #region public method

        #region UnicodeToPlain

        public static string ToPlainText(object _unicodeText)
        {
            return ToPlainText(_unicodeText.ToString(), false);
        }



        public static string ToPlainText(string _unicodeText, bool _replaceCharacters)
        {

            _unicodeText = _unicodeText.Trim();
            if (string.IsNullOrEmpty(_unicodeText)) return string.Empty;

            ////Remove VietNamese character
            //_unicodeText = _unicodeText.ToLower();
            //_unicodeText = Regex.Replace(_unicodeText, "[áàảãạâấầẩẫậăắằẳẵặ]", "a");
            //_unicodeText = Regex.Replace(_unicodeText, "[éèẻẽẹêếềểễệ]", "e");
            //_unicodeText = Regex.Replace(_unicodeText, "[iíìỉĩị]", "i");
            //_unicodeText = Regex.Replace(_unicodeText, "[óòỏõọơớờởỡợôốồổỗộ]", "o");
            //_unicodeText = Regex.Replace(_unicodeText, "[úùủũụưứừửữự]", "u");
            //_unicodeText = Regex.Replace(_unicodeText, "[ýỳỷỹỵ]", "y");
            //_unicodeText = Regex.Replace(_unicodeText, "[đ]", "d");

            ////Remove space

            //if (_replaceCharacters)
            //{



            //    _unicodeText = _unicodeText.Replace(" ", "-").Replace("&", "-").Replace("+", "-").Replace("/", "-").Replace(":", "-");
            
            //    //Remove special character
            //    _unicodeText = Regex.Replace(_unicodeText, "[`~!@#$%^&*()-+=?/>.<,{}[]|]\\“”\"]", string.Empty);

            //    _unicodeText = RemoveExtraHyphen(_unicodeText);
            //}

            //return _unicodeText;

           


            int _length = _unicodeText.Length;

            var _sb = new StringBuilder(_length);

            for (int i = 0; i < _length; i++)
            {

                char _char = _unicodeText[i];
                // char _charTemp;

                switch (_char)
                {

                    case 'đ':
                        _sb.Append('d');
                        break;
                    case 'Đ':
                        _sb.Append('D');
                        break;
                    case 'à':
                    case 'á':
                    case 'ạ':
                    case 'ả':
                    case 'ã':
                    case 'ă':
                    case 'ằ':
                    case 'ắ':
                    case 'ẳ':
                    case 'ặ':
                    case 'ẵ':
                    case 'â':
                    case 'ầ':
                    case 'ấ':
                    case 'ẩ':
                    case 'ẫ':
                    case 'ậ':
                        _sb.Append('a');
                        break;
                    case 'À':
                    case 'Á':
                    case 'Ạ':
                    case 'Ả':
                    case 'Ã':
                    case 'Ă':
                    case 'Ằ':
                    case 'Ắ':
                    case 'Ẳ':
                    case 'Ặ':
                    case 'Ẵ':
                    case 'Â':
                    case 'Ầ':
                    case 'Ấ':
                    case 'Ẩ':
                    case 'Ẫ':
                    case 'Ậ':
                        _sb.Append('A');
                        break;
                    case 'è':
                    case 'é':
                    case 'ẹ':
                    case 'ẻ':
                    case 'ẽ':
                    case 'ê':
                    case 'ề':
                    case 'ế':
                    case 'ể':
                    case 'ệ':
                    case 'ễ':
                        _sb.Append('e');
                        break;
                    case 'È':
                    case 'É':
                    case 'Ẹ':
                    case 'Ẻ':
                    case 'Ẽ':
                    case 'Ê':
                    case 'Ề':
                    case 'Ế':
                    case 'Ể':
                    case 'Ệ':
                    case 'Ễ':
                        _sb.Append('E');
                        break;

                    case 'ò':
                    case 'ó':
                    case 'ọ':
                    case 'ỏ':
                    case 'õ':
                    case 'ơ':
                    case 'ờ':
                    case 'ớ':
                    case 'ở':
                    case 'ợ':
                    case 'ỡ':
                    case 'ô':
                    case 'ồ':
                    case 'ố':
                    case 'ổ':
                    case 'ộ':
                    case 'ỗ':
                        _sb.Append('o');
                        break;
                    case 'Ò':
                    case 'Ó':
                    case 'Ọ':
                    case 'Ỏ':
                    case 'Õ':
                    case 'Ơ':
                    case 'Ờ':
                    case 'Ớ':
                    case 'Ở':
                    case 'Ợ':
                    case 'Ỡ':
                    case 'Ô':
                    case 'Ồ':
                    case 'Ố':
                    case 'Ổ':
                    case 'Ộ':
                    case 'Ỗ':
                        _sb.Append('O');
                        break;
                    case 'ù':
                    case 'ú':
                    case 'ụ':
                    case 'ủ':
                    case 'ũ':
                    case 'ư':
                    case 'ừ':
                    case 'ứ':
                    case 'ử':
                    case 'ự':
                    case 'ữ':
                        _sb.Append('u');
                        break;
                    case 'Ù':
                    case 'Ú':
                    case 'Ụ':
                    case 'Ủ':
                    case 'Ũ':
                    case 'Ư':
                    case 'Ừ':
                    case 'Ứ':
                    case 'Ử':
                    case 'Ự':
                    case 'Ữ':
                        _sb.Append('U');
                        break;
                    case 'ỳ':
                    case 'ý':
                    case 'ỵ':
                    case 'ỷ':
                    case 'ỹ':
                        _sb.Append('y');
                        break;
                    case 'Ỳ':
                    case 'Ý':
                    case 'Ỵ':
                    case 'Ỷ':
                    case 'Ỹ':
                        _sb.Append('Y');
                        break;
                    case 'ì':
                    case 'í':
                    case 'ị':
                    case 'ỉ':
                    case 'ĩ':
                        _sb.Append('i');
                        break;
                    case 'Ì':
                    case 'Í':
                    case 'Ị':
                    case 'Ỉ':
                    case 'Ĩ':
                        _sb.Append('I');
                        break;
                    default:
                        _sb.Append(_char);
                        break;
                }

            }

            if (_replaceCharacters)
            {


                _sb.Replace(" ", "-");
                _sb.Replace("&", "-");
                _sb.Replace("+", "-");
                _sb.Replace("/", "-");
                _sb.Replace(":", "-");
                _sb.Replace(",", "-");
                _sb.Replace("?", String.Empty);
                _sb.Replace(".", String.Empty);
                _sb.Replace("\"", String.Empty);
                _sb.Replace("~", String.Empty);
                _sb.Replace("^", String.Empty);
                _sb.Replace("*", String.Empty);
                _sb.Replace("%", String.Empty);
                _sb.Replace(">", String.Empty);
                _sb.Replace("<", String.Empty);
                _sb.Replace("`", String.Empty);
                _sb.Replace("|", String.Empty);
                _sb.Replace("'", String.Empty);
                _sb.Replace("#", String.Empty);
                _sb.Replace("”", String.Empty);
                _sb.Replace("“", String.Empty);
                _sb.Replace(")", String.Empty);
                _sb.Replace("(", String.Empty);
                _sb.Replace("}", String.Empty);
                _sb.Replace("{", String.Empty);

                return RemoveExtraHyphen(_sb.ToString());
            }
            
              return _sb.ToString();
            





        }
        #endregion


        #region #IP Address

        public static string ClientIP
        {
            get
            {
                //return HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                //string _ip = HttpContext.Current.Request.UserHostAddress;
                //if (_ip == "::1") return "127.0.0.1";
                //return _ip;

                string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                if (!String.IsNullOrEmpty(result))
                {
                    if (result.IndexOf(".") == -1)
                    {
                        result = null;
                    }
                    else if (result.IndexOf(",") != -1)
                    {
                        result = result.Replace(" ", "").Replace("'", "");
                        string[] tempIP = result.Split(",;".ToCharArray());
                        // int i1 = Microsoft.VisualBasic.Information.UBound(tempIP, 1);
                        for (int i = 0; i <= tempIP.Length; i++)
                        {
                            if (IsIPAddress(tempIP[i]) && !tempIP[i].StartsWith("10.") && !tempIP[i].StartsWith("192.168") && !tempIP[i].StartsWith("172.16."))
                                return tempIP[i];
                        }
                    }
                    else
                    {
                        if (IsIPAddress(result))
                            return result;
                        result = null;
                    }
                }
                if (String.IsNullOrEmpty(result))
                    result = HttpContext.Current.Request.UserHostAddress;
                return result;
            }

        }


        public static bool IsIPAddress(string ip)
        {
            bool result = true;
            if (!Regex.IsMatch(ip, @"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$"))
            {
                return false;
            }
            string[] IPSeg = ip.Split('.');
            if (IPSeg.Length != 3)
            {
                return false;
            }
            int i = 0;
            do
            {
                if ((int.Parse(IPSeg[i]) > 255) || (int.Parse(IPSeg[i]) < 0))
                {
                    result = false;
                }
                i++;
            }
            while (i <= 3);
            return result;
        }

        public static long IP2Long(string ip)
        {

            string[] ipBytes;

            double num = 0;

            if (!string.IsNullOrEmpty(ip))
            {

                ipBytes = ip.Split('.');

                for (int i = ipBytes.Length - 1; i >= 0; i--)
                {

                    num += ((int.Parse(ipBytes[i]) % 256) * Math.Pow(256, (3 - i)));

                }

            }

            return (long)num;

        }

        static public string LongToIP(long longIP)
        {

            string ip = string.Empty;

            for (int i = 0; i < 4; i++)
            {

                int num = (int)(longIP / Math.Pow(256, (3 - i)));

                longIP = longIP - (long)(num * Math.Pow(256, (3 - i)));

                if (i == 0)

                    ip = num.ToString();

                else

                    ip = ip + "." + num;

            }

            return ip;

        }

        #endregion


      
       


        /// <summary>
        /// sanitize any potentially dangerous tags from the provided raw HTML input using 
        /// a whitelist based approach, leaving the "safe" HTML tags
        /// CODESNIPPET:4100A61A-1711-4366-B0B0-144D1179A937
        /// </summary>
        //public static string Sanitize(string html)
        //{
        //    if (String.IsNullOrEmpty(html)) return html;

        //    Match tag;

        //    // match every HTML tag in the input
        //    MatchCollection tags = _tags.Matches(html);
        //    for (int i = tags.Count - 1; i > -1; i--)
        //    {
        //        tag = tags[i];
        //        string tagname = tag.Value.ToLowerInvariant();

        //        if (!(_whitelist.IsMatch(tagname) || _whitelist_a.IsMatch(tagname) || _whitelist_img.IsMatch(tagname)))
        //        {
        //            html = html.Remove(tag.Index, tag.Length);
        //            System.Diagnostics.Debug.WriteLine("tag sanitized: " + tagname);
        //        }
        //    }

        //    return html;
        //}


        #region ScrubHTML
        /*
        public static string ScrubHTML(string html)
        {
            var doc = new HtmlDocument();
            doc.LoadHtml(html);

            //Remove potentially harmful elements
            HtmlNodeCollection nc = doc.DocumentNode.SelectNodes("//script|//link|//iframe|//frameset|//frame|//applet|//object|//embed");
            if (nc != null)
            {
                foreach (HtmlNode node in nc)
                {
                    node.ParentNode.RemoveChild(node, false);

                }
            }

            //remove hrefs to java/j/vbscript URLs
            nc = doc.DocumentNode.SelectNodes("//a[starts-with(translate(@href, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'javascript')]|//a[starts-with(translate(@href, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'jscript')]|//a[starts-with(translate(@href, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'vbscript')]");
            if (nc != null)
            {

                foreach (HtmlNode node in nc)
                {
                    node.SetAttributeValue("href", "#");
                }
            }


            //remove img with refs to java/j/vbscript URLs
            nc = doc.DocumentNode.SelectNodes("//img[starts-with(translate(@src, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'javascript')]|//img[starts-with(translate(@src, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'jscript')]|//img[starts-with(translate(@src, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'vbscript')]");
            if (nc != null)
            {
                foreach (HtmlNode node in nc)
                {
                    node.SetAttributeValue("src", "#");
                }
            }

            //remove on<Event> handlers from all tags
            nc = doc.DocumentNode.SelectNodes("//*[@onclick or @onmouseover or @onfocus or @onblur or @onmouseout or @ondoubleclick or @onload or @onunload]");
            if (nc != null)
            {
                foreach (HtmlNode node in nc)
                {
                    node.Attributes.Remove("onFocus");
                    node.Attributes.Remove("onBlur");
                    node.Attributes.Remove("onClick");
                    node.Attributes.Remove("onMouseOver");
                    node.Attributes.Remove("onMouseOut");
                    node.Attributes.Remove("onDoubleClick");
                    node.Attributes.Remove("onLoad");
                    node.Attributes.Remove("onUnload");
                }
            }

            // remove any style attributes that contain the word expression (IE evaluates this as script)
            // or position
            nc = doc.DocumentNode.SelectNodes("//*[contains(translate(@style, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'expression')] | //*[contains(translate(@style, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'position')] ");
            if (nc != null)
            {
                foreach (HtmlNode node in nc)
                {
                    node.Attributes.Remove("stYle");
                }
            }

            return doc.DocumentNode.WriteTo();
        }
         * */
    #endregion


        public static string ClearHtmlTags(string source)
        {
            if (string.IsNullOrEmpty(source))
                return source;
            string temp = source;
            while (temp.IndexOf('<') != -1 && temp.IndexOf('>') != -1)
            {
                int start = temp.IndexOf('<');
                int end = temp.IndexOf('>');
                temp = temp.Remove(start, end - start + 1);
            }
            return temp;
        }

        public static string BadWordFilter(string source, string badWord)
        {

            if (string.IsNullOrEmpty(badWord))
            {
                return source;
            }
            string pattern = string.Format("(?:{0})", badWord);
            return Regex.Replace(source, pattern, "****", RegexOptions.IgnoreCase);
        }

        public static bool IsGraphic(string FileName)
        {
            //var Regex = new Regex(@"\.gif$|\.jpg$|\.jpeg$|\.png$|\.bmp$|\.tiff$|\.wmf$|\.ico$", RegexOptions.IgnoreCase);
            Regex _Regex = new Regex(@"\.gif$|\.jpg$|\.jpeg$|\.png$|\.bmp$", RegexOptions.IgnoreCase);
            if (_Regex.IsMatch(FileName))
            {
                return true;
            }
            return false;
        }


        public static string Truncate(object _input, int _length)
        {

            string _outPut = _input.ToString();

            // int  = ForumConfiguration.Instance.TopicShowWordsLength;

            if (_outPut.Length <= _length)
            {
                return _outPut;

            }
            //else

            string[] _words = _outPut.Replace("&nbsp;", " ").Split(' ');
            var _sb = new StringBuilder(250);
            foreach (string _t in _words)
            {
                if (_t.Length > _length)
                {
                    _sb.Append(_t.Substring(0, _length));

                }
                else if ((_sb + _t).Length < _length)
                {
                    _sb.Append(" " + _t);
                }
            }


            return _sb + "...";
        }


        //public static string TruncateAtWord(this string value, int length)
        //{
        //    if (value == null || value.Length < length || value.IndexOf(" ", length) == -1)
        //        return value;

        //    return value.Substring(0, value.IndexOf(" ", length));
        //}

        //public static string TruncateAtWord(this string input, int length)
        //{
        //    if (input == null || input.Length < length)
        //        return input;
        //    int iNextSpace = input.LastIndexOf(" ", length);
        //    return string.Format("{0}...", input.Substring(0, (iNextSpace > 0) ? iNextSpace : length).Trim());
        //}



        public static bool Compare(string _a, string _b)
        {
            return String.Compare(_a, _b, StringComparison.OrdinalIgnoreCase) == 0;
        }

        /// <summary>
        /// Turns a bool into an int
        /// </summary>
        /// <param name="Input">Bool value</param>
        /// <returns>Int equivalent</returns>
        public static int BoolToInt(bool Input)
        {
            return Input ? 1 : 0;
        }

        /// <summary>
        /// Turns an int into a bool
        /// </summary>
        /// <param name="Input">Int value</param>
        /// <returns>bool equivalent</returns>
        public static bool IntToBool(int Input)
        {
            return Input > 0 ? true : false;
        }

        public static bool IsNumber(object Input)
        {
            //if (Input is int) return true;
            //if(Input is double || Input is Int64 || Double is Int64) 

            try
            {
                Convert.ToDouble(Input);
                return true;
            }
            catch (Exception)
            {

                return false;
            }
        }

        /// <summary>
        /// Takes the numeric value and returns the day of the week.
        /// </summary>
        /// <param name="DayOfWeek">The int representation of the day of the week</param>
        /// <returns>returns the string value for the day of the week</returns>
        public static string IntToDay(int DayOfWeek)
        {
            switch (DayOfWeek)
            {
                case 1:
                    return "Sunday";
                case 2:
                    return "Monday";
                case 3:
                    return "Tuesday";
                case 4:
                    return "Wednesday";
                case 5:
                    return "Thursday";
                case 6:
                    return "Friday";
                case 7:
                    return "Saturday";
            }
            return "";
        }

        /// <summary>
        /// Takes the day of the week and returns the numeric value (1-7).
        /// </summary>
        /// <param name="DayOfWeek">The string representation of the day of the week</param>
        /// <returns>returns the int value for the day of the week</returns>
        public static int DayToInt(string DayOfWeek)
        {
            switch (DayOfWeek)
            {
                case "Sunday":
                    return 1;
                case "Monday":
                    return 2;
                case "Tuesday":
                    return 3;
                case "Wednesday":
                    return 4;
                case "Thursday":
                    return 5;
                case "Friday":
                    return 6;
                case "Saturday":
                    return 7;
            }
            return 0;
        }

        /// <summary>
        /// Takes the int value for the month and returns the name of the month
        /// </summary>
        /// <param name="Month">The month in int form</param>
        /// <returns>returns the string value for the month</returns>
        public static string IntMonthToString(int Month)
        {
            switch (Month)
            {
                case 1:
                    return "January";
                case 2:
                    return "February";
                case 3:
                    return "March";
                case 4:
                    return "April";
                case 5:
                    return "May";
                case 6:
                    return "June";
                case 7:
                    return "July";
                case 8:
                    return "August";
                case 9:
                    return "September";
                case 10:
                    return "October";
                case 11:
                    return "November";
                case 12:
                    return "December";
                default:
                    return "";
            }
        }

        /// <summary>
        /// Takes the int value for the month and returns the name of the month
        /// </summary>
        /// <param name="Month">The month in int form</param>
        /// <returns>returns the string value for the month</returns>
        public static int StringToIntMonth(string Month)
        {
            switch (Month)
            {
                case "January":
                    return 1;
                case "February":
                    return 2;
                case "March":
                    return 3;
                case "April":
                    return 4;
                case "May":
                    return 5;
                case "June":
                    return 6;
                case "July":
                    return 7;
                case "August":
                    return 8;
                case "September":
                    return 9;
                case "October":
                    return 10;
                case "November":
                    return 11;
                case "December":
                    return 12;
                default:
                    return 0;
            }
        }


        public static List<DateTime> DaysOfDateRange(DateTime startingDate, DateTime endingDate)
        {
            if (startingDate > endingDate)
            {
                return null;
            }
            List<DateTime> rv = new List<DateTime>();
            DateTime tmpDate = startingDate;
            do
            {
                rv.Add(tmpDate);
                tmpDate = tmpDate.AddDays(1);
            } while (tmpDate <= endingDate);
            return rv;
        }


        /// <summary>
        /// Converts base 64 string to normal string
        /// </summary>
        /// <param name="Input">Input string</param>
        /// <returns>normal string (non base 64)</returns>
        public static string Base64ToString(string Input)
        {
            if (string.IsNullOrEmpty(Input))
                return "";
            byte[] TempArray = Convert.FromBase64String(Input);
            return Encoding.UTF8.GetString(TempArray);
        }

        /// <summary>
        /// Converts a normal string to base 64 string
        /// </summary>
        /// <param name="Input">Input string</param>
        /// <returns>A base 64 string</returns>
        public static string StringToBase64(string Input)
        {
            if (string.IsNullOrEmpty(Input))
                return "";
            byte[] TempArray = Encoding.UTF8.GetBytes(Input);
            return Convert.ToBase64String(TempArray);
        }


        public static bool IsEmail(string _email)
        {
            string pattern = @"^[a-z][a-z|0-9|]*([_][a-z|0-9]+)*([.][a-z|" +
               @"0-9]+([_][a-z|0-9]+)*)?@[a-z][a-z|0-9|]*\.([a-z]" +
               @"[a-z|0-9]*(\.[a-z][a-z|0-9]*)?)$";
            Match match = Regex.Match(_email.Trim(), pattern, RegexOptions.IgnoreCase);

            if (match.Success)
                return true;
            else
                return false;
        }


        public static long RemoteUrlSize(string url)
        {
            var _req = (HttpWebRequest)WebRequest.Create(url);
            _req.Method = "HEAD";
            var _resp = (HttpWebResponse)(_req.GetResponse());
            return _resp.ContentLength;

        }

        #endregion








    }
}
